
#include "abcrypto.h"

#include "main.h"
#include "common.h"

int test_auth(void)
{
	int ret = -1;
	uint32_t len;
	uint8_t *data = NULL;
	uint8_t *adata = NULL;
	uint8_t result[2][128] = { 0 };
	struct abcrypto_auth *aauth;
	struct abcrypto_auth *bauth;
	void *aauth_ctx = NULL;
	void *bauth_ctx = NULL;
	uint32_t local_loop = loop;
	uint8_t *key = NULL;
	uint32_t diff = 0;
	uint32_t local_klen = 16;

	aauth = a_instance->get_auth(test_alg);
	if (aauth == NULL) {
		fprintf(stderr, "Not find auth %s implement in %s instance\n",
			get_algo_name(test_alg), a_instance->name);
		goto out;
	}

	bauth = b_instance->get_auth(test_alg);
	if (bauth == NULL) {
		fprintf(stderr, "Not find auth %s implement in %s instance\n",
			get_algo_name(test_alg), b_instance->name);
		goto out;
	}

	data = malloc(elen + alen);
	if (data == NULL) {
		fprintf(stderr, "Malloc failed, %s line %d\n", __func__,
			__LINE__);
		goto out;
	}

	key = malloc(1024);
	if (key == NULL) {
		fprintf(stderr, "Malloc failed, %s line %d\n", __func__,
			__LINE__);
		goto out;
	}

	adata = data;

	while (local_loop--) {
		get_rand(adata, elen + alen);
		get_rand(key, 1024);

		data = adata + alen;
		/* test init update final && digest */
		for (len = slen; len <= elen; len += test_step) {
			/*rand localklen*/
			local_klen = len % 1024 + 1;

			if (aauth->init_ctx(&aauth_ctx, key, local_klen,
					    test_alg)) {
				fprintf(stderr,
					"Init ctx failed in auth %s implement in %s instance\n",
					get_algo_name(test_alg),
					a_instance->name);
				goto out;
			}

			if (bauth->init_ctx(&bauth_ctx, key, local_klen,
					    test_alg)) {
				fprintf(stderr,
					"Init ctx failed in auth %s implement in %s instance\n",
					get_algo_name(test_alg),
					b_instance->name);
				goto out;
			}

			if (alen)
				aauth->update(aauth_ctx, adata, alen);

			aauth->update(aauth_ctx, data, len);
			aauth->finish(aauth_ctx, result[0]);
			aauth->free_ctx(aauth_ctx);

			if (alen)
				bauth->update(bauth_ctx, adata, alen);

			bauth->update(bauth_ctx, data, len);
			bauth->finish(bauth_ctx, result[1]);
			bauth->free_ctx(bauth_ctx);

			/* a init update final, b init updata final */
			if (memcmp(result[0], result[1], 128)) {
				fprintf(stderr,
					"Dismatch results[ii] len %u %s\n", len,
					get_algo_name(test_alg));
				print_buf(a_instance->name, result[0], 128);
				print_buf(b_instance->name, result[1], 128);
				print_buf("data", adata, alen + len);
				print_buf("key", key, local_klen);
				diff++;
				if (!test_skip)
					goto out;
				else
					continue;
			}

			/*a init upate final, b digest*/
			memset(result[1], 0, 128);
			bauth->digest(adata, alen + len, key, local_klen,
				      result[1], test_alg);
			if (memcmp(result[0], result[1], 128)) {
				fprintf(stderr,
					"Dismatch results[id] len %u %s\n", len,
					get_algo_name(test_alg));
				print_buf(a_instance->name, result[0], 128);
				print_buf(b_instance->name, result[1], 128);
				print_buf("data", adata, alen + len);
				print_buf("key", key, local_klen);

				diff++;
				if (!test_skip)
					goto out;
				else
					continue;
			}

			/*a digest b digest*/
			memset(result[0], 0, 128);
			aauth->digest(adata, alen + len, key, local_klen,
				      result[0], test_alg);
			if (memcmp(result[0], result[1], 128)) {
				fprintf(stderr,
					"Dismatch results[dd] len %u %s\n", len,
					get_algo_name(test_alg));
				print_buf(a_instance->name, result[0], 128);
				print_buf(b_instance->name, result[1], 128);
				print_buf("data", adata, alen + len);
				print_buf("key", key, local_klen);
				diff++;
				if (!test_skip)
					goto out;
				else
					continue;
			}
		}
	}

	ret = 0;
out:
	if (diff)
		printf("Test alg %s failed,  slen %u, elen %u, loop %u, diff %u\n",
		       get_algo_name(test_alg), slen, elen, loop, diff);
	else
		printf("Test alg %s success, slen %u, elen %u, loop %u\n",
		       get_algo_name(test_alg), slen, elen, loop);

	if (key)
		free(key);

	if (adata)
		free(adata);

	return ret;
}